//! # 重试机制测试模块

use super::*;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use tokio::time::Duration;

#[tokio::test]
async fn test_exponential_backoff_strategy() {
    let strategy = ExponentialBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_secs(30),
        2.0
    ).with_max_attempts(5);
    
    // 测试延迟计算
    assert_eq!(strategy.calculate_delay(0), Duration::from_millis(100));
    assert_eq!(strategy.calculate_delay(1), Duration::from_millis(100));
    assert_eq!(strategy.calculate_delay(2), Duration::from_millis(200));
    assert_eq!(strategy.calculate_delay(3), Duration::from_millis(400));
    
    // 测试重试条件
    let error = crate::ResilienceError::internal_error("test error");
    assert!(strategy.should_retry(0, &error));
    assert!(strategy.should_retry(4, &error));
    assert!(!strategy.should_retry(5, &error));
    
    assert_eq!(strategy.max_attempts(), 5);
}

#[tokio::test]
async fn test_linear_backoff_strategy() {
    let strategy = LinearBackoffStrategy::new(
        Duration::from_millis(100),
        Duration::from_millis(50)
    ).with_max_attempts(4);
    
    // 测试延迟计算
    assert_eq!(strategy.calculate_delay(0), Duration::from_millis(100));
    assert_eq!(strategy.calculate_delay(1), Duration::from_millis(150));
    assert_eq!(strategy.calculate_delay(2), Duration::from_millis(200));
    assert_eq!(strategy.calculate_delay(3), Duration::from_millis(250));
    
    assert_eq!(strategy.max_attempts(), 4);
}

#[tokio::test]
async fn test_fixed_delay_strategy() {
    let strategy = FixedDelayStrategy::new(Duration::from_millis(500))
        .with_max_attempts(3);
    
    // 测试延迟计算
    assert_eq!(strategy.calculate_delay(0), Duration::from_millis(500));
    assert_eq!(strategy.calculate_delay(1), Duration::from_millis(500));
    assert_eq!(strategy.calculate_delay(5), Duration::from_millis(500));
    
    assert_eq!(strategy.max_attempts(), 3);
}

#[tokio::test]
async fn test_retry_executor_success() {
    let config = RetryConfig {
        max_attempts: 3,
        backoff_strategy: BackoffStrategy::Fixed { 
            delay: Duration::from_millis(10) 
        },
        retry_conditions: vec![RetryCondition::NetworkError],
        budget_percent: 10.0,
        jitter_enabled: false,
        timeout: None,
    };
    
    let executor = RetryExecutor::new(config);
    let attempt_count = Arc::new(AtomicU32::new(0));
    let count_clone = attempt_count.clone();
    
    let result = executor.execute(move || {
        let count = count_clone.clone();
        async move {
            let current = count.fetch_add(1, Ordering::Relaxed) + 1;
            if current < 3 {
                Err(crate::ResilienceError::internal_error("临时失败"))
            } else {
                Ok("成功")
            }
        }
    }).await;
    
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), "成功");
    assert_eq!(attempt_count.load(Ordering::Relaxed), 3);
}

#[tokio::test]
async fn test_retry_executor_max_attempts() {
    let config = RetryConfig {
        max_attempts: 2,
        backoff_strategy: BackoffStrategy::Fixed { 
            delay: Duration::from_millis(10) 
        },
        retry_conditions: vec![RetryCondition::NetworkError],
        budget_percent: 10.0,
        jitter_enabled: false,
        timeout: None,
    };
    
    let executor = RetryExecutor::new(config);
    let attempt_count = Arc::new(AtomicU32::new(0));
    let count_clone = attempt_count.clone();
    
    let result = executor.execute(move || {
        let count = count_clone.clone();
        async move {
            count.fetch_add(1, Ordering::Relaxed);
            Err(crate::ResilienceError::internal_error("持续失败"))
        }
    }).await;
    
    assert!(result.is_err());
    assert_eq!(attempt_count.load(Ordering::Relaxed), 2);
}

#[tokio::test]
async fn test_retry_executor_non_retryable_error() {
    let config = RetryConfig {
        max_attempts: 3,
        backoff_strategy: BackoffStrategy::Fixed { 
            delay: Duration::from_millis(10) 
        },
        retry_conditions: vec![RetryCondition::Timeout], // 只重试超时错误
        budget_percent: 10.0,
        jitter_enabled: false,
        timeout: None,
    };
    
    let executor = RetryExecutor::new(config);
    let attempt_count = Arc::new(AtomicU32::new(0));
    let count_clone = attempt_count.clone();
    
    let result = executor.execute(move || {
        let count = count_clone.clone();
        async move {
            count.fetch_add(1, Ordering::Relaxed);
            // 这个错误类型不在重试条件中，应该立即失败
            Err(crate::ResilienceError::config_error("配置错误"))
        }
    }).await;
    
    assert!(result.is_err());
    // 应该只尝试一次，因为错误不可重试
    assert_eq!(attempt_count.load(Ordering::Relaxed), 1);
}

#[test]
fn test_backoff_strategy_calculate_delay() {
    // 测试固定延迟策略
    let fixed = BackoffStrategy::Fixed { delay: Duration::from_millis(1000) };
    assert_eq!(fixed.calculate_delay(0), Duration::from_millis(1000));
    assert_eq!(fixed.calculate_delay(3), Duration::from_millis(1000));
    
    // 测试线性增长策略
    let linear = BackoffStrategy::Linear { 
        initial_delay: Duration::from_millis(100), 
        increment: Duration::from_millis(50) 
    };
    assert_eq!(linear.calculate_delay(0), Duration::from_millis(100));
    assert_eq!(linear.calculate_delay(2), Duration::from_millis(200));
    
    // 测试指数退避策略
    let exponential = BackoffStrategy::Exponential { 
        initial_delay: Duration::from_millis(100), 
        max_delay: Duration::from_secs(5), 
        multiplier: 2.0 
    };
    assert_eq!(exponential.calculate_delay(0), Duration::from_millis(100));
    assert_eq!(exponential.calculate_delay(3), Duration::from_millis(800));
    
    // 测试最大延迟限制
    let capped_delay = exponential.calculate_delay(10);
    assert!(capped_delay <= Duration::from_secs(5));
}

#[test]
fn test_retry_conditions() {
    // 测试重试条件枚举的序列化/反序列化
    let conditions = vec![
        RetryCondition::NetworkError,
        RetryCondition::Timeout,
        RetryCondition::HttpStatusRange(500, 599),
        RetryCondition::ErrorType("connection".to_string()),
        RetryCondition::Custom("custom_condition".to_string()),
    ];
    
    for condition in conditions {
        let serialized = serde_json::to_string(&condition).unwrap();
        let deserialized: RetryCondition = serde_json::from_str(&serialized).unwrap();
        
        // 验证序列化和反序列化的一致性
        match (&condition, &deserialized) {
            (RetryCondition::NetworkError, RetryCondition::NetworkError) => {},
            (RetryCondition::Timeout, RetryCondition::Timeout) => {},
            (RetryCondition::HttpStatusRange(s1, e1), RetryCondition::HttpStatusRange(s2, e2)) => {
                assert_eq!(s1, s2);
                assert_eq!(e1, e2);
            },
            (RetryCondition::ErrorType(t1), RetryCondition::ErrorType(t2)) => {
                assert_eq!(t1, t2);
            },
            (RetryCondition::Custom(c1), RetryCondition::Custom(c2)) => {
                assert_eq!(c1, c2);
            },
            _ => panic!("序列化/反序列化不匹配"),
        }
    }
}

#[test]
fn test_retry_config_default() {
    let config = RetryConfig::default();
    
    assert_eq!(config.max_attempts, 3);
    assert!(config.jitter_enabled);
    assert_eq!(config.budget_percent, 10.0);
    assert!(config.timeout.is_some());
    
    // 验证默认退避策略
    match config.backoff_strategy {
        BackoffStrategy::Exponential { initial_delay, max_delay, multiplier } => {
            assert_eq!(initial_delay, Duration::from_millis(1000));
            assert_eq!(max_delay, Duration::from_secs(30));
            assert_eq!(multiplier, 2.0);
        },
        _ => panic!("Expected exponential backoff strategy"),
    }
    
    // 验证默认重试条件
    assert_eq!(config.retry_conditions.len(), 3);
    assert!(config.retry_conditions.contains(&RetryCondition::NetworkError));
    assert!(config.retry_conditions.contains(&RetryCondition::Timeout));
    assert!(config.retry_conditions.contains(&RetryCondition::HttpStatusRange(500, 599)));
}

#[test]
fn test_retry_stats_default() {
    let stats = RetryStats::default();
    
    assert_eq!(stats.total_retries, 0);
    assert_eq!(stats.successful_retries, 0);
    assert_eq!(stats.failed_retries, 0);
    assert_eq!(stats.average_attempts, 0.0);
    assert!(stats.last_updated <= chrono::Utc::now());
}

#[tokio::test]
async fn test_retry_with_jitter() {
    let config = RetryConfig {
        max_attempts: 3,
        backoff_strategy: BackoffStrategy::Fixed { 
            delay: Duration::from_millis(100) 
        },
        retry_conditions: vec![RetryCondition::NetworkError],
        budget_percent: 10.0,
        jitter_enabled: true, // 启用択动
        timeout: None,
    };
    
    let executor = RetryExecutor::new(config);
    
    // 测试多次计算延迟，验证择动效果
    let delays: Vec<Duration> = (0..10)
        .map(|_| executor.calculate_delay(1))
        .collect();
    
    // 验证延迟时间有变化（由于择动）
    let all_same = delays.windows(2).all(|w| w[0] == w[1]);
    assert!(!all_same, "启用择动时，延迟时间应该有变化");
    
    // 验证所有延迟都在合理范围内（基础延迟的 90%-110%）
    let base_delay_ms = 100;
    for delay in delays {
        let delay_ms = delay.as_millis() as u64;
        assert!(delay_ms >= 90 && delay_ms <= 110, 
            "择动延迟 {} ms 不在预期范围内", delay_ms);
    }
}

#[tokio::test]
async fn test_retry_executor_immediate_success() {
    let config = RetryConfig::default();
    let executor = RetryExecutor::new(config);
    let attempt_count = Arc::new(AtomicU32::new(0));
    let count_clone = attempt_count.clone();
    
    let result = executor.execute(move || {
        let count = count_clone.clone();
        async move {
            count.fetch_add(1, Ordering::Relaxed);
            Ok("立即成功")
        }
    }).await;
    
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), "立即成功");
    // 应该只尝试一次
    assert_eq!(attempt_count.load(Ordering::Relaxed), 1);
}